package com.koron.order.patrol.business.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.github.pagehelper.PageInfo;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadCallback;
import com.github.tobato.fastdfs.service.DefaultFastFileStorageClient;
import com.koron.bean.base.Attachment;
import com.koron.bean.base.Response;
import com.koron.bean.query.PageQuery;
import com.koron.common.core.business.common.service.AttachmentService;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.order.patrol.bean.dto.PatrolDto;
import com.koron.order.patrol.bean.po.PatrolPointPo;
import com.koron.order.patrol.bean.query.PatrolQuery;
import com.koron.order.patrol.bean.vo.PatrolBaseVo;
import com.koron.order.patrol.bean.vo.PatrolExportVo;
import com.koron.order.patrol.bean.vo.PatrolPointVo;
import com.koron.order.patrol.bean.vo.PatrolVo;
import com.koron.order.patrol.business.service.PatrolBusinessService;
import com.koron.order.patrol.service.PatrolPointService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.koron.ebs.mybatis.ADOConnection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 巡视工单-基础信息(Patrol)表控制层
 * PatrolBusinessController
 *
 * @author zhouj
 * @since 2021-10-26 15:32:40
 */
@Api(tags = "巡视工单-业务接口(Patrol)")
@RestController
@RequestMapping("/patrol/")
@Slf4j
public class PatrolBusinessController {

    @Autowired
    PatrolBusinessService patrolBusinessService;

    @Autowired
    private PatrolPointService patrolPointService;
    //附件
    @Autowired
    private AttachmentService attachmentService;
    @Autowired
    private DefaultFastFileStorageClient storageClient;

    private String getCurrDs() {
        return ThreadLocalContext.get().getCurrDs();
    }

    @ApiOperation(value = "新建或修改巡视工单")
    @PostMapping("insertOrUpdate")
    public Response<String> insertOrUpdate(@RequestBody PatrolDto patrolDto) {
        return Response.ok(ADOConnection.runTask(getCurrDs(), patrolBusinessService, "insertOrUpdate", String.class, patrolDto));
    }

    @ApiOperation(value = "根据orderId查询巡视工单详情页信息")
    @GetMapping("queryPatrolDtoByOrderId")
    public Response<PatrolDto> queryPatrolDtoByOrderId(String orderId) {
        return Response.ok(ADOConnection.runTask(getCurrDs(), patrolBusinessService, "queryPatrolDtoByOrderId", PatrolDto.class, orderId));
    }

    @ApiOperation(value = "移动端根据orderId下载巡视工单详情页信息")
    @GetMapping("queryPatrolAllDtoByOrderId")
    public Response<PatrolDto> queryPatrolAllDtoByOrderId(String orderId) {
        //移动端需要一次性下载该工单全部数据,需要优化
        return Response.ok(ADOConnection.runTask(getCurrDs(), patrolBusinessService, "queryPatrolAllDtoByOrderId", PatrolDto.class, orderId));
    }

    @ApiOperation(value = "根据orderId查询巡视工单基本信息")
    @GetMapping("queryByOrderId")
    public Response<PatrolBaseVo> queryByOrderId(String orderId) {
        return Response.ok(ADOConnection.runTask(getCurrDs(), patrolBusinessService, "queryByOrderId", PatrolBaseVo.class, orderId));
    }

    @ApiOperation(value = "根据巡视点id查询巡视工单巡视情况")
    @GetMapping("queryByPatrolPointId")
    public Response<PatrolPointVo> queryByPatrolPointId(String patrolPointId) {
        return Response.ok(ADOConnection.runTask(getCurrDs(), patrolBusinessService, "queryByPatrolPointId", PatrolPointVo.class, patrolPointId));
    }

    @ApiOperation(value = "巡视工单分页列表")
    @GetMapping("queryVoPageList")
    public Response<PageInfo<PatrolVo>> queryVoPageList(PatrolQuery query, PageQuery pageQuery) {
        return Response.ok(ADOConnection.runTask(getCurrDs(), patrolBusinessService, "queryVoPageList", PageInfo.class, query, pageQuery));
    }

    @ApiOperation(value = "插入主表以及巡视人员数据")
    @PostMapping("insertPatrolUser")
    public Response<PatrolDto> insertPatrolUser(@RequestBody PatrolDto patrolDto) {
        ADOConnection.runTask(getCurrDs(), patrolBusinessService, "insertPatrolUser", String.class, patrolDto);
        return Response.ok(patrolDto);
    }


    /**
     *  @author xxxn
     *  @description: 将巡视工单所有图片打包下载
     *  @date 2022/08/10
     *  @param orderId   工单Id
     *  @param response 请求相应
     *  @param request  请求
     */
    @ApiOperation("将巡视工单所有图片打包下载")
    @GetMapping({"/downloadPatrolZip"})
    @ApiImplicitParams({
            @ApiImplicitParam(name = "zipName", value = "附件的名称(默认：附件)", required = false, paramType = "query"),
            @ApiImplicitParam(name = "orderId", value = "工单Id", required = true, paramType = "string"),
    })
    public void downloadPatrolZip(@RequestParam(defaultValue = "附件",required = false) String zipName,@RequestParam String orderId,HttpServletResponse response, HttpServletRequest request) {
        //setCurrDs(currDs);
        try  {
            //查询工单下的所有巡视点信息
            PatrolPointPo patrolPointPo = new PatrolPointPo();
            patrolPointPo.setPatrolId(orderId);
            List<PatrolPointPo> pointList = ADOConnection.runTask(getCurrDs(), patrolPointService, "queryList", List.class, patrolPointPo);
            if (CollectionUtils.isEmpty(pointList)) {
                response.setHeader("Content-Type", "text/html;charset=UTF-8");
                response.getOutputStream().write("巡视点为空".getBytes());
                return;
            }
            //判断下工单下的巡视点有没有图片
            List<Attachment> reportList = attachmentService.getAttachmentListByBusinessIdsWithType(pointList.stream().map(PatrolPointPo::getId).toArray(String[]::new), null);
            if (CollectionUtils.isEmpty(reportList)) {
                response.setHeader("Content-Type", "text/html;charset=UTF-8");
                response.getOutputStream().write("没有巡视点附件".getBytes());
                return;
            }

            //开始构建压缩包

            byte[] buffers = new byte[10240];
            // 创建一个新的 byte 数组输出流，它具有指定大小的缓冲区容量
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            //创建一个新的缓冲输出流，以将数据写入指定的底层输出流
            BufferedOutputStream fos = new BufferedOutputStream(baos);
            ZipOutputStream zos = new ZipOutputStream(fos);

            for (PatrolPointPo pointPoOne : pointList) {
                List<Attachment> attachmentList = attachmentService.getAttachmentListByBusinessIdWithTypeWithSubBusinessId(pointPoOne.getId(), null, null);
                if (CollectionUtils.isEmpty(attachmentList)) {
                    continue;
                }
                for (int j = 0; j < attachmentList.size(); j++) {
                    //获取各个文件的数据流
                    Attachment attachmentOne = attachmentList.get(j);
                    StorePath storePath = StorePath.parseFromUrl(attachmentOne.getPath());
                    storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), (DownloadCallback<ResponseEntity>) inputStream -> {
                        zos.putNextEntry(new ZipEntry(pointPoOne.getName()+"/"+attachmentOne.getName()));
                        int length;
                        while ((length = inputStream.read(buffers)) > 0) {
                            //将文件读入压缩文件内
                            zos.write(buffers, 0, length);
                        }
                        zos.closeEntry();
                        inputStream.close();
                        return null;
                    });
                }
            }

            zos.close();
            fos.flush();

            try (
                    OutputStream _os = response.getOutputStream();
                    InputStream is = new ByteArrayInputStream(baos.toByteArray());
            ) {

                byte[] buffer1 = new byte[1024 * 5];
                int len = 0;
                while ((len = is.read(buffer1)) > 0) {
                    _os.write(buffer1, 0, len);
                }
                _os.flush();
            } catch (IOException e) {
                response.setHeader("Content-Type", "text/html;charset=UTF-8");
                response.getOutputStream().write("附件不存在".getBytes());
                return;
            }
            baos.close();
            fos.close();
            response.setHeader("Content-Type", "application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(zipName, "UTF-8"));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            try (OutputStream os = response.getOutputStream()) {
                response.setHeader("Content-Type", "text/html;charset=UTF-8");
                os.write("附件下载失败".getBytes());
            } catch (Exception e1) {
                log.error(e.getMessage(), e1);
            }
        }
    }


    /**
     * @param orderId 工单Id
     * @author xxxn
     * @description: 巡视工单下载前的检查(检查工单有没有附件)
     * @date 2022/08/12
     */
    @ApiOperation("巡视工单下载前的检查")
    @GetMapping({"/downloadPatrolCheck"})
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderId", value = "工单Id", required = true, paramType = "string"),
    })
    public Response<List<Attachment>> downloadPatrolCheck(@RequestParam String orderId) {
        //查询工单下的所有巡视点信息
        PatrolPointPo patrolPointPo = new PatrolPointPo();
        patrolPointPo.setPatrolId(orderId);
        List<PatrolPointPo> pointList = ADOConnection.runTask(getCurrDs(), patrolPointService, "queryList", List.class, patrolPointPo);
        Assert.notEmpty(pointList, "没有巡视点");
        //判断下工单下的巡视点有没有图片
        List<Attachment> reportList = attachmentService.getAttachmentListByBusinessIdsWithType(pointList.stream().map(PatrolPointPo::getId).toArray(String[]::new), null);
        Assert.notEmpty(reportList, "没有附件");
        return Response.ok(reportList);
    }


    @SneakyThrows
    @ApiOperation(value = "巡视点导出")
    @PostMapping("export")
    public void exportPatrol(@RequestBody PatrolQuery query,HttpServletResponse response){
        List<PatrolExportVo> result = ADOConnection.runTask(getCurrDs(), patrolBusinessService, "queryVoList", List.class, query);
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("巡视工单-巡视点导出", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), PatrolExportVo.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("巡视工单-巡视点导出")
                .doWrite(result);
    }

}
